#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <mpi.h>

#define STRSIZE 45
#define NTHREAD 2

void clear_str(char *c, int n);
int main(int argc, char *argv[]) {

	FILE *fp;
	char aux[STRSIZE],c;
	char *frase = (char*)malloc(sizeof(char));
	int pa = 0,tpa=0;
	int pf=0,tpf=0;
	int tamanho_frase=0;
	int tamanho_arquivo;
	int passo_arquivo;
	int inicio_arquivo;
	int fim_frase;
	/*Variáveis MPI */   
	int dest,noProcesses, processId, src, tag;
	MPI_Status status;   

	/* Inicializacção do MPI */   
	MPI_Init(&argc, &argv);   
	MPI_Comm_size(MPI_COMM_WORLD, &noProcesses);
	MPI_Comm_rank(MPI_COMM_WORLD, &processId);

	if ( (fp = fopen(argv[1],"r")) == NULL ) 
	{
		printf("Erro ao abrir o arquivo.\n");
		exit(1);
	}


	clear_str(aux,STRSIZE);

	//divide os arquivos para cada processo
	fseek(fp, 0, SEEK_END);
	tamanho_arquivo= ftell(fp);
	passo_arquivo=(int)(tamanho_arquivo/noProcesses);
	inicio_arquivo=passo_arquivo*processId;
	//printf("processo %d inicio %d \n",processId,inicio_arquivo);	
	fseek(fp, inicio_arquivo, SEEK_SET);

	//le até a proxima frase
	if(processId!=0)
		while (c != '.' && c != ':' && c != '?'&& c != '!')
		{
			c=getc(fp);
			if(c==EOF)// se o texto conter uma unica frase o loop nao terminaria 
				break;
		}
			
	//agora vai até o final da frase
	tamanho_frase=1;
	fim_frase=0;
	while((ftell(fp)< passo_arquivo*(processId + 1) || fim_frase ==0) && !feof(fp)) 
	{
		fim_frase=0;
		clear_str(aux,STRSIZE);
		fscanf(fp,"%s",aux);
		pa += palindromo(aux);
		tamanho_frase+=strlen(aux);
		frase=(char*)realloc(frase,sizeof(char)*tamanho_frase);
		strcat(frase,aux); 
		if(frase[strlen(frase)-1]=='.' || frase[strlen(frase)-1]==':' || frase[strlen(frase)-1]=='?' || frase[strlen(frase)-1]=='!')
		{
			pf += palindromo(frase);
			clear_str(frase,tamanho_frase);
			tamanho_frase=1;
			fim_frase=1;	
		}
   	}

	//recuperando os dados.
	tag=0;
	if(processId==0)//se for 0 recupera os resultados
	{
		tpf=pf;
		tpa=pa;
		for (src=1; src < noProcesses; src++)
		{
			MPI_Recv(&pf, 1, MPI_DOUBLE, src, tag, MPI_COMM_WORLD,&status);
			tpf+=pf;
			MPI_Recv(&pa, 1, MPI_DOUBLE, src, tag, MPI_COMM_WORLD,&status);
			tpa+=pa;
		}
		printf("Total de Palindromo de Palavra: %d\n",tpa);
		printf("Total de Palindromo de frase: %d\n",tpf);
	}
	else //demais enviam resultado
	{
		dest = 0;       
		MPI_Send(&pf, 1, MPI_DOUBLE, dest, tag, MPI_COMM_WORLD);
		MPI_Send(&pa, 1, MPI_DOUBLE, dest, tag, MPI_COMM_WORLD);
	}
	    
	//printf("pa: %d processo numero %d\n",pa,processId);
	//printf("pf: %d processo numero %d\n",pf,processId);

	MPI_Finalize( );

	fclose(fp);
	fflush(stdout);
	return 0;

}

void clear_str(char *c, int n) {

    int i = 0;

    for ( i = 0; i < n; i++ ) {
        c[i] = 0;
    }

}

int palindromo(char *str) {

    int i,l,j;
    int ssize = strlen(str);

    i=0;
    j=ssize-1;
    //ignorando caracteres especiais no final de palavra, no final da palavra, exem.: (kfbrwiufh)
    for(l=j;l>=0;l--)
        if((int)str[l]<65 || ((int)str[l]>90 && (int)str[l]<97) || (int)str[l]>122 )
	{
		if(str[l]==',')
			str[l]=0;
                j--;
	}
        else
                break;

    //ignorando caracteres especiais no inicio de palavra, no final da palavra, exem.: (kfbrwiufh)
    for(l=0;l<=j;l++)
        if((int)str[l]<65 || ((int)str[l]>90 && (int)str[l]<97) || (int)str[l]>122 )
                i++;
        else
                break;
    
    //se passar aq é palimdrome
    if(j==-1)
        return 0;//isso significa e existe uma palavra com apenas simbolos especiais
    for (  ;i < j;i++){
        if (   ((int)str[j] != (int)str[i])   &&         ((int)str[j]+32 != (int)str[i])   && ((int)str[j] != (int)str[i]+32)         )
                return 0;
        j--;
    }
    //printf("%s ",str);
    return 1;

}
